package apigateway.project.core.filter;

import apigateway.project.commen.config.Rule;
import apigateway.project.core.aspect.FilterAspect;
import apigateway.project.core.context.GlobalContext;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import lombok.Getter;

import java.lang.annotation.Annotation;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

import static apigateway.project.commen.constant.FilterConst.ROUTER_FILTER_ID;

public class GatewayFilterChainFactory implements FilterChainFactory{

    private GatewayFilterChainFactory(){
        //加载所有注解开启的过滤器
        ServiceLoader<Filter> serviceLoader = ServiceLoader.load(Filter.class);
        serviceLoader.stream().forEach(filterProvider -> {
            Filter filter = filterProvider.get();
            FilterAspect annotation = filter.getClass().getAnnotation(FilterAspect.class);
            if(annotation != null){
                String filterId = annotation.value();
                if(filterId != null && !filterId.isEmpty()){
                    filterIdMap.put(filterId, filter);
                }
            }
        });
    };

    @Getter
    private static final GatewayFilterChainFactory gatewayFilterChainFactory = new GatewayFilterChainFactory();

    private Map<String,Filter> filterIdMap= new ConcurrentHashMap<>();
    /**
     * 使用本地缓存生成的过滤器链,过期时间10分钟
     */
    private Cache<String,GatewayFilterChain> FilterChainCache = Caffeine.newBuilder()
            .expireAfterWrite(10, TimeUnit.MINUTES)
            .build();

    @Override
    public GatewayFilterChain createChain(GlobalContext ctx) {
        return FilterChainCache.get(ctx.getRule().getId(),k->doCreateFilterChain(ctx.getRule()));
    }

    private GatewayFilterChain doCreateFilterChain(Rule rule) {
        GatewayFilterChain chain = new GatewayFilterChain();
        List<Filter> filterList = new ArrayList<>();
        if(rule!=null){
            Map<String, String> filters = rule.getFilters();
            if(filters!=null && !filters.isEmpty()){
                filters.forEach((filterId, filterConfig) -> {
                    if(filterIdMap.containsKey(filterId)){
                        Filter filter = filterIdMap.get(filterId);
                        filterList.add(filter);
                    }
                });
            }
        }
        // 最后加入路由过滤器
        filterList.add(filterIdMap.get(ROUTER_FILTER_ID));
        // 按照Order注解排序
        filterList.sort(Comparator.comparingInt(Filter::getOrder));
        // 添加到chain中
        chain.addList(filterList);

        return chain;
    }

}
